var config = require('../../config');
var configOauth = config.oauth;
var PassportWxAuthenticator = require('fw-commonweb/base/oauth/passport/passport_wx_authenticator');
var JwtUsernamePasswordAuthenticator = require('fw-commonweb/base/oauth/passport/jwt_username_password_authenticator');

var JwtAuthenticator = require('fw-commonweb/base/oauth/jwt_authenticator');

var WxAuthenticator = require('fw-commonweb/base/oauth/wx_authenticator');

var TokenClient = require('fw-commonweb/base/oauth/token/token_client');

var passport = require('passport');

var tokenExtractor = require('fw-commonweb/base/oauth/token/header_token_extractor');

var CookieToken = require('../token');


var Token = new CookieToken(config.token.cookie);

passport.use(new PassportWxAuthenticator({

    wxAuthenticator: new WxAuthenticator({
        clientId: configOauth.serverClientId,
        clientSecret: configOauth.serverClientSecret,
        authorizeUrl: configOauth.wxAuthorize,
        accessTokenUrl: configOauth.serverAccessTokenUrl,
        redirectUrl: configOauth.redirectUrl,
        defaultClient: configOauth.defaultClient
    })

}, function (accessToken, done) {
    done(null, accessToken);
}));


passport.use(new JwtUsernamePasswordAuthenticator({

    jwtAuthenticator: new JwtAuthenticator({
        clientId: configOauth.serverClientId,
        clientSecret: configOauth.serverClientSecret,
        accessTokenUrl: configOauth.serverAccessTokenUrl,
        scope: 'fwapi_base'
    })

}, function (accessToken, done) {
    done(null, accessToken);
}));


var tokenClient = new TokenClient({
    clientId: configOauth.serverClientId,
    clientSecret: configOauth.serverClientSecret,
    accessTokenUrl: configOauth.serverAccessTokenUrl
});
var domain = config.domain;
var router = function (app) {
    app.get('/**', function (req, res, next) {
        var token = Token.get(req);
        if (token) {
            if (tokenClient.isExpired(token)) {
                tokenClient.refresh(token, function (newToken) {

                    if (newToken && newToken.access_token) {
                        Token.set(newToken, req, res);
                        req.token = newToken;
                    } else {
                        console.warn('refresh token failed', newToken);
                    }
                }, function () {
                    console.warn('refresh token failed', arguments);
                });
            } else {
                req.token = token;
            }
        }
        next();
    });

    app.get('/**', function (req, res, next) {
        var token = req.token;
        if (token && token.hasOwnProperty('access_token')) {
            next();
        } else {
            req.query.redirect = domain + req.originalUrl;
            passport.authenticate(configOauth.passportStrategy, {
                params: {
                    client: req.query.client,
                    username: req.query.user,
                    password: req.query.password || req.query.user,
                    scope: 'wx'
                },
                session: false
            }, function (err, user, info) {
                if (user && user.access_token) {
                    Token.set(user, req, res);
                    req.token = user;
                    next();
                } else {
                    if (info && info.redirect) {
                        res.redirect(info.redirect);
                    } else {
                        res.json(info);
                    }
                }
            })(req, res, next);
        }
    });


    app.post('/oauth/token/refresh', function (req, res) {

        var token = tokenExtractor.extract(req);

        if (token && token.access_token) {
            tokenClient.refresh(token, function (newToken) {

                if (newToken && newToken.access_token) {
                    res.json(newToken);
                    Token.set(newToken, req, res);
                } else {
                    res.json({
                        msg: 'refresh token failed'
                    });
                }
            }, function () {
                res.json({
                    msg: 'no access token provided'
                });
            });

        }


    });


};


module.exports = router;